package com.juyu.miliao.api.service;

import com.alibaba.fastjson.JSONObject;
import com.juyu.miliao.api.dao.mysql.*;
import com.juyu.miliao.api.dao.redis.SmsSenderRedisDao;
import com.juyu.miliao.api.domain.BillDetail;
import com.juyu.miliao.api.domain.UserBindWxInfo;
import com.juyu.miliao.api.domain.UserWallet;
import com.juyu.miliao.api.domain.dto.WxBindingDTO;
import com.juyu.miliao.api.domain.vo.WxUserInfoVo;
import com.juyu.miliao.api.util.Md5Util;
import com.juyu.miliao.common.constant.RecordTypeEnum;
import com.juyu.miliao.common.domain.CommonHead;
import com.juyu.miliao.common.domain.ConfigSms;
import com.juyu.miliao.common.exception.ConsumeRuntimeException;
import com.juyu.miliao.common.util.SmsSender;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author xuanqicheng
 * @create 2019-27-12:35
 */
@Service
@Slf4j
public class WxBindingService {

    /**
     * 手机验证码key
     */
    private static final String WX_BINDING_PHONE_CODE = "WX_BINDING_PHONE_CODE:";

    /**
     * 微信领取金币key
     */
    private static final String WX_GET_GOLD_KEY = "MILIAO_WX_BINDING_USER_GET_GOLD:";

    private static final String SECRET_KEY = "*L@z@^d8w1T%Ugll";
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private UserAuthenticationInfoDao userAuthenticationInfoDao;

    @Autowired
    private UserBindWxInfoDao userBindWxInfoDao;

    @Autowired
    private UserWalletDao userWalletDao;

    @Autowired
    private BillDetailDao billDetailDao;
    @Resource
    private SmsSenderRedisDao smsSenderRedisDao;
    @Resource
    private ConfigSmsDao configSmsDao;


    public void sendPhoneNumValidateCode(String phone, String validateCode, CommonHead com) {

        checkPhoneIsBinding(phone);

        if(smsSenderRedisDao.isMemberBlacklist(phone)){
            throw new ConsumeRuntimeException("手机号异常");
        }
        if(smsSenderRedisDao.isMember(phone)){
            throw new ConsumeRuntimeException("手机号1分钟内不能重复发送短信");
        }
//        Double score = smsSenderRedisDao.scoreSmsSenderEveryDay(phone);
//        if(score != null && score > 10){
//            throw new ConsumeRuntimeException("该手机号发送数量受限");
//        }
        //发送短信
//        SmsSender smsSender = new SmsSender(phone,"【寻寻】绑定验证码"+validateCode+"，十分钟内有效，请尽快完成绑定。");
        SmsSender smsSender = new SmsSender(phone,349689,validateCode);
        smsSender.sendSms(com,getConfigSmsSing(com));
        String key = WX_BINDING_PHONE_CODE+phone;
        stringRedisTemplate.opsForValue().set(key,validateCode,10, TimeUnit.MINUTES);
        smsSenderRedisDao.addSmsSender(phone);
//        smsSenderRedisDao.addSmsSenderByEveryDay(phone);
    }
    private  String getConfigSmsSing(CommonHead com){
        List<ConfigSms> configSmsList = configSmsDao.listConfigSms();
        String sign = "";
        String huamiSign = "";
        for(ConfigSms c : configSmsList){
            if (c.getAppPackageId().equals("huami")){
                huamiSign = c.getSignId();
            }
            if(c.getAppPackageId().equals(com.getAppPackageId())){
                sign = c.getSignId();
            }
        }
        if(sign.equals(""))
            sign = huamiSign;
        return sign;
    }

    public Object getWxBinding(WxBindingDTO wxBindingDTO) {

        List<Long> userList=checkPhoneIsBinding(wxBindingDTO.getPhone());

        String key = WX_BINDING_PHONE_CODE+wxBindingDTO.getPhone();

        String code =stringRedisTemplate.opsForValue().get(key);

        if(StringUtils.isEmpty(code)){
            throw  new ConsumeRuntimeException("验证码过期");
        }

        if(!code.equals(wxBindingDTO.getCode())){

            throw new ConsumeRuntimeException("验证码不正确,请重新填写");
        }


        long userId = userList.get(0);

        //根据open
        UserBindWxInfo userBindWxInfo =userBindWxInfoDao.getUserBindWxByOpenid(wxBindingDTO.getOpenid());
        if(userBindWxInfo==null){
            userBindWxInfo = new UserBindWxInfo();
            userBindWxInfo.setUserId(userId);
            userBindWxInfo.setOpenid(wxBindingDTO.getOpenid());
            userBindWxInfo.setIsGold(0);
            userBindWxInfoDao.insert(userBindWxInfo);
            //领取金币秘钥操作
            Map<String,Object> map = getSecretkey(userId,wxBindingDTO.getOpenid(),5,wxBindingDTO.getPhone(),
                    wxBindingDTO.getCode());
            return map;
        }else{
            if(userBindWxInfo.getIsGold()==0){
                //领取金币秘钥操作
                Map<String,Object> map = getSecretkey(userId,wxBindingDTO.getOpenid(),5,wxBindingDTO.getPhone(),
                        wxBindingDTO.getCode());

                return map;

            }else{
                if(userId == userBindWxInfo.getUserId()){

                    throw new ConsumeRuntimeException("用户已领取过金币");

                }else{
                    throw new ConsumeRuntimeException("用户绑定的微信号不正确");
                }
            }
        }

    }

    /**
     * 生成领取金币秘钥
     * @param userId
     * @param openid
     * @param gold
     * @param phone
     * @param code
     * @return
     */
    private Map<String,Object> getSecretkey(long userId,String openid,int gold,String phone,String code){

        String secret = Md5Util.md5Encode(openid+phone+code+SECRET_KEY);

        String key = WX_GET_GOLD_KEY+secret;

        JSONObject json = new JSONObject();

        json.put("userId",userId);

        json.put("openid",openid);

        json.put("gold",gold);

        stringRedisTemplate.opsForValue().set(key,json.toJSONString(),10,TimeUnit.MINUTES);

        Map<String,Object> map = new HashMap<>(1);

        map.put("secret",secret);

        return map;
    }



    /**
     * 检查手机号是否注册或绑定过
     * @param phone
     */
    private List<Long> checkPhoneIsBinding(String phone) {

        List<Long> userList = userAuthenticationInfoDao.selectUserIdByPhone(phone);

        if(userList.size()==0){
            throw new ConsumeRuntimeException("此手机号未绑定花蜜账号，请重新输入");
        }

        return userList;
    }

    /**
     * 领取金币
     * @param secret
     * @return
     */
    public Object getGoldBySecret(String secret) {

        String key = WX_GET_GOLD_KEY+secret;

        if(stringRedisTemplate.hasKey(key)){

            String target = stringRedisTemplate.opsForValue().get(key);

            JSONObject json = JSONObject.parseObject(target);

            long userId = json.getLongValue("userId");

            String openid = json.getString("openid");

            int gold = json.getIntValue("gold");

            UserBindWxInfo userBindWxInfo =userBindWxInfoDao.getUserBindWxByOpenid(openid);

            if(userBindWxInfo !=null){

                if(userBindWxInfo.getIsGold()==0 ){

                    Map<String,Object> map = saveGold(userId,gold);

                    return map;

                }else{
                    if(userId == userBindWxInfo.getUserId()){

                        throw new ConsumeRuntimeException("用户已领取过金币");

                    }else{

                        throw new ConsumeRuntimeException("用户绑定的微信号不正确");
                    }
                }

            }else{
                throw new ConsumeRuntimeException("secret不正确，请重新获取");
            }

        }else{
            throw new ConsumeRuntimeException("secret已过期");
        }
    }



    private Map<String,Object> saveGold(long userId,int gold) {
        //领取金币
        int num = userBindWxInfoDao.updateGoldStatus(userId);
        if(num !=1){
            throw new ConsumeRuntimeException("用户已领取过金币");
        }
        //加金币
        UserWallet userWallet = new UserWallet();

        userWallet.setDeposit(5);

        userWallet.setUserId(userId);

        userWalletDao.reviseDeposit(userWallet);

        // 保存消费记录
        BillDetail billDetail = new BillDetail();

        billDetail.setRecordType(RecordTypeEnum.USER_BINDING_WX.state);

        billDetail.setInUserId(userId);

        billDetail.setDiamond(0);

        billDetail.setSpend(5);

        billDetailDao.insertBillDetail(billDetail);

        log.info("关注领金币5个成功："+userId);

        Map<String,Object> map = new HashMap<>(1);
        map.put("msg","领取金币成功");
        map.put("gold",5);
        return map;
    }
}
